//
//  NetLayer.swift
//  TODOApp
//
//  Created by chenyh on 2018/5/24.
//  Copyright © 2018年 chenyh. All rights reserved.
//

@_exported import Alamofire
/// 日志输出
///
/// - Parameters:
///   - message: 输出内容
///   - file: 所在文件
///   - method: 所在方法
///   - line: 所在行
func printLog<T>(_ message: T,
                 file: String = #file,
                 method: String = #function,
                 line: Int = #line)
{
    #if DEBUG
    print("🐶年🐶🐶大吉🐶\((file as NSString).lastPathComponent)[\(line),\(method):\(message)]")
    #else
    #endif
}

//MARK:请求协议 将这些全部封装到Config中
public protocol Request {
    /// 请求的一切参数 封装成一个配置文件
    var requestModel: RequestConfiguration {get}
    
}

public typealias HTTPComplement = (BaseModel?,Error?) -> ()


/// 请求消息
public protocol RequestSender {
    /// 请求主机地址
    var host: String { get }

    /// 发起一个请求
    ///
    /// - Parameters:
    ///   - r: 请求实体
    ///   - block: 请求结果回调
    /// - Returns: 返回Void
    func send<T: Request>(_ r: T,block: @escaping HTTPComplement) -> Void
    
}

//MARK:文件model
public struct RequestData{
    /// 扩展名
    var extensionName: String?
    /// 二进制数据数组
    var fileDatas: [Data?]?
    /// 二进制数据数组丢应的文件名
    var datasName: String?
    /// 元信息
    var mimeType: String!
}

//MARK:请求实体
public struct RequestConfiguration {
    
    var requestConfig: (ControllerType,ApiRequestList)!
    /// 请求参数
    var requestParams: [String: Any]?
    
    /// 请求是否带HUD
    var requestIsHUD: Bool = false
    
    /// 请求HUD文本
    var requestAlertText: String? = "正在加载..."
    
    /// 请求方式
    var requestType: HTTPMethod = .post
    
    /// 请求头
    var requestHeaderFormat: HTTPHeaders = TODOToolManager.CommonTool.getToken().isEmpty ? ["Content-Type" : "application/json"] : ["Content-Type" : "application/json","Authorization": TODOToolManager.CommonTool.getToken() ]
    /// 请求编码
    var requestEncode: ParameterEncoding = JSONEncoding.default
    
    /// 多媒体数据实体
    var requestData: RequestData? = nil
    
}


public struct  NetLayerRequestSender: RequestSender
{
    public let host: String = TODOToolManager.CommonTool.getHostPath()
    
    public func send<T: Request>(_ r: T,block: @escaping HTTPComplement) -> Void {
        
        printLog(Thread.current)
        //TODO:1.判断网络
        let domainStatus = NetworkReachabilityManager(host: host)
        if domainStatus!.networkReachabilityStatus == .notReachable  {
            printLog("没有网络")

        }
        
        
        //TODO:2.拼接地址
        let requestUrl = "\(host)\(r.requestModel.requestConfig.0.rawValue)\(r.requestModel.requestConfig.1.api())"

        //TODO:3.输出参数和URL ->
        printLog(requestUrl + "\(r.requestModel.requestParams ?? [:])")
        
        //TODO:5.---->配置请求session
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 20
        configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
        let sessionManager = Alamofire.SessionManager(configuration: configuration)
        
        //TODO:6.---->判断是否存在多媒体数据
        if r.requestModel.requestData != nil {
           uploadImages(r.requestModel,
                        path: requestUrl,
                        session: sessionManager,
                        complement: block)
            
        }else{
            getOrPostRequest(r.requestModel,
                             path: requestUrl,
                             session: sessionManager,
                             complement: block)
           
        }
        
        
    }
    
    static func kShowOrHideNetworkActivityIndicator(_ displayNetwork: Bool) {
        
        DispatchQueue.main.async {
            UIApplication.shared.isNetworkActivityIndicatorVisible = displayNetwork;
        }
        
    }
    
    private func uploadImages(_ configuration: RequestConfiguration,path: String, session: SessionManager,complement: @escaping HTTPComplement) {

            NetLayerRequestSender.kShowOrHideNetworkActivityIndicator(true)
    
            session.upload(multipartFormData: { (formData) in
                if configuration.requestParams != nil {
                    for (k,v) in configuration.requestParams!{
                        if let vData = "\(v)".data(using: .utf8) {
                            formData.append(vData, withName: k)
                        }
                    }
                }
                if let datas = configuration.requestData!.fileDatas {
                    
                    for (i,data) in datas.filterNil().enumerated() {
                        printLog("\(Date().timeIntervalSince1970)"+"_\(i)_." + configuration.requestData!.extensionName!)
                        formData.append(data,
                                        withName:configuration.requestData!.datasName!,
                                        fileName:"\(Date().timeIntervalSince1970)"+"_\(i)_." + configuration.requestData!.extensionName!,
                                        mimeType: configuration.requestData!.mimeType)
                    }
                }
                //先添加参数
            }, to: path,method: configuration.requestType,headers: configuration.requestHeaderFormat, encodingCompletion: { (encodingResult) in
                
                NetLayerRequestSender.kShowOrHideNetworkActivityIndicator(false)
                
                switch (encodingResult) {
                    
                case let .success(request,_,_):
                    request.responseJSON {
                        if let error = $0.error {
                            complement(nil,error)
                        }
                        
                        if let dict = try? JSONSerialization.jsonObject(with: $0.data!, options: .mutableContainers) as? Dictionary<String, Any>,let dictValue = dict,let statusCode = dictValue["status"] as? Int {
                         
                            let baseModel = BaseModel(message:
                                dictValue["message"] as? String ?? "", status: statusCode == 0 ? 1 : statusCode, result: dict!["result"])
                            complement(baseModel, nil)
                            
                        }else{
                           
                            if #available(iOS 11.0, *) {
                                complement(nil,NSError(domain: "com.todo.error", code: 1, userInfo: [NSLocalizedFailureErrorKey:"数据格式错误"]))
                            } else {
                                // Fallback on earlier versions
                                
                                complement(nil,NSError(domain: "com.todo.error", code: 1, userInfo: [NSStringEncodingErrorKey:"数据格式错误"]))
                            }
                        }
                        
                    }
                    
                    case let .failure(encodingError):
                       
                        complement(nil,encodingError)
                }
            }
        )
    }
    
    private  func getOrPostRequest(_ configuration: RequestConfiguration,path: String,session: SessionManager,complement: @escaping HTTPComplement) -> Void {
        
          Alamofire.request(path,
                            method: configuration.requestType,
                            parameters: configuration.requestParams,
                            encoding: configuration.requestEncode,
                        headers:configuration.requestHeaderFormat)
                .responseJSON(queue: DispatchQueue.global(qos: .background), options:        JSONSerialization.ReadingOptions.mutableContainers, completionHandler: { (responseObject) in
                    printLog(responseObject.description)
                    NetLayerRequestSender.kShowOrHideNetworkActivityIndicator(false)
  
                    if let error = responseObject.error {
                        complement(nil,error)
                    }
                    if let dict = try? JSONSerialization.jsonObject(with: responseObject.data!, options: .mutableContainers) as? Dictionary<String, Any>,let dictValue = dict,let statusCode = dictValue["status"] as? Int {
                    let baseModel = BaseModel(message:
                        dictValue["message"] as? String ?? "", status: statusCode == 0 ? 1 : statusCode, result: dict!["result"])
                    complement(baseModel, nil)
               
                    }else {
                        if #available(iOS 11.0, *) {
                            complement(nil,NSError(domain: "com.todo.error", code: 1, userInfo: [NSLocalizedFailureErrorKey:"数据格式错误"]))
                        } else {
                            // Fallback on earlier versions
                            
                            complement(nil,NSError(domain: "com.todo.error", code: 1, userInfo: [NSStringEncodingErrorKey:"数据格式错误"]))
                        }
                }
                }).resume()
    }
}
